<!doctype html>
<html lang="en">
<head>
    <title>Polyhedra (Three.js)</title>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
    <link rel=stylesheet href="css/base.css"/>
</head>
<body>

<script src="js/Three58.js"></script>
<script src="js/Detector.js"></script>

<script src="js/TrackballControls.js"></script>

<script src="js/polyhedra.js"></script>

<div id="ThreeJS" style="position: absolute; left:0px; top:0px"></div>
<script>
/*
	Three.js "tutorials by example"
	Author: Lee Stemkoski
	Date: July 2013 (three.js v59dev)
 */

// MAIN

// standard global variables
var container, scene, camera, renderer, controls, stats;

// var clock = new THREE.Clock();

// custom global variables
var mesh;

init();
animate();

// FUNCTIONS 		
function init() 
{
	// SCENE
	scene = new THREE.Scene();
	// CAMERA
	var SCREEN_WIDTH = window.innerWidth, SCREEN_HEIGHT = window.innerHeight;
	var VIEW_ANGLE = 45, ASPECT = SCREEN_WIDTH / SCREEN_HEIGHT, NEAR = 0.1, FAR = 20000;
	camera = new THREE.PerspectiveCamera( VIEW_ANGLE, ASPECT, NEAR, FAR);
	scene.add(camera);
	camera.position.set(0,150,400);
	camera.lookAt(scene.position);	
	// RENDERER
	if ( Detector.webgl )
		renderer = new THREE.WebGLRenderer( {antialias:true} );
	else
		renderer = new THREE.CanvasRenderer(); 
	renderer.setSize(SCREEN_WIDTH, SCREEN_HEIGHT);
	container = document.getElementById( 'ThreeJS' );
	container.appendChild( renderer.domElement );
	// CONTROLS
	controls = new THREE.TrackballControls( camera, renderer.domElement );
	controls.noPan = true;
	// LIGHT
	var light = new THREE.PointLight(0xffffff);
	// light.position.set(100,250,100);
	light.position = camera.position;
	scene.add(light);
	var light = new THREE.PointLight(0x888888);
	light.position.set(-100,-250,-100);
	scene.add(light);
	
	// SKYBOX
	var skyBoxGeometry = new THREE.CubeGeometry( 10000, 10000, 10000 );
	var skyBoxMaterial = new THREE.MeshBasicMaterial( { color: 0xccccff, side: THREE.BackSide } );
	var skyBox = new THREE.Mesh( skyBoxGeometry, skyBoxMaterial );
	scene.add(skyBox);
	
	////////////
	// CUSTOM //
	////////////
		
	this.polyhedronMesh = polyhedronDataToMesh( POLYHEDRA.TruncatedIcosidodecahedron );
	polyhedronMesh.scale.multiplyScalar(0.90);
	scene.add(polyhedronMesh);
	
	// SPRITE GUI?
	var ballTexture = THREE.ImageUtils.loadTexture( 'images/redball.png' );
	var ballMaterial = new THREE.SpriteMaterial( { color: 0x0000ff, map: ballTexture, useScreenCoordinates: true, alignment: THREE.SpriteAlignment.bottomLeft } );
	var sprite = new THREE.Sprite( ballMaterial );
	sprite.position.set( 5, window.innerHeight - 5, 0 );
	sprite.scale.set( 128, 128, 1.0 ); // imageWidth, imageHeight
	scene.add( sprite );
	
	
	
	
} // end of function init()

var faces;

function displayMesh(mesh)
{
scene.remove(polyhedronMesh);
polyhedronMesh = mesh;
scene.add(polyhedronMesh);
}

function polyhedronDataToMesh(data)
{
	var polyhedron = new THREE.Object3D();
	
	//var chromeTexture = new THREE.ImageUtils.loadTexture( 'images/Chrome.png' );
	//var chromeMaterial = new THREE.MeshBasicMaterial( { color:0x999900, map: chromeTexture} );
		 
	// convert vertex data to THREE.js vectors
	var vertex = [] 
	for (var i = 0; i < data.vertex.length; i++)
		vertex.push( new THREE.Vector3( data.vertex[i][0], data.vertex[i][1], data.vertex[i][2] ).multiplyScalar(100) );

	// render vertices as spheres
	var vertexGeometry = new THREE.SphereGeometry( 6, 32, 16 );
	var vertexMaterial = new THREE.MeshLambertMaterial( { color: 0x222244 } );
	var mesh = new THREE.Mesh( vertexGeometry, vertexMaterial );

	var vertexAmalgam = new THREE.Geometry();
	for (var i = 0; i < data.vertex.length; i++)
	{
		var vMesh = mesh.clone();
		vMesh.position = vertex[i];
		THREE.GeometryUtils.merge( vertexAmalgam, vMesh );
		// polyhedron.add(vMesh);
	}
	var vertexMesh = new THREE.Mesh( vertexAmalgam, vertexMaterial );
	polyhedron.add( vertexMesh );
	
	// convert edge data to cylinders
	var edgeMaterial = new THREE.MeshLambertMaterial( {color: 0x666666} );
	var edgeAmalgam = new THREE.Geometry();
	for (var i = 0; i < data.edge.length; i++)
	{
		var index0 = data.edge[i][0];
		var index1 = data.edge[i][1];
		var eMesh = cylinderMesh( vertex[index0], vertex[index1], edgeMaterial );
		THREE.GeometryUtils.merge( edgeAmalgam, eMesh );
		// polyhedron.add(eMesh);
		//var outline = eMesh.clone();
		//outline.setMaterial( new THREE.MeshBasicMaterial({color:0x000000, side:THREE.BackSide}) );
		//outline.scale.x = outline.scale.z = 1.5;
		//scene.add(outline);
	}
	var edgeMesh = new THREE.Mesh( edgeAmalgam, edgeMaterial );
	polyhedron.add( edgeMesh );
	// convert face data to a single (triangulated) geometry
	var faceMaterial = new THREE.MeshBasicMaterial( { color: 0xffffff, vertexColors: THREE.FaceColors }); //, side: THREE.DoubleSide  transparent:true, opacity:0.8 } );
	var faceColors = 
	{
		// cc0000 663300 cccc00 00cc00 0000cc 660066 brown-663300 
	    3: new THREE.Color( 0xcc0000 ),
	    4: new THREE.Color( 0x00cc00 ),
	    5: new THREE.Color( 0x0000cc ),
	    6: new THREE.Color( 0xcccc00 ),
	    7: new THREE.Color( 0x999999 ),
	    8: new THREE.Color( 0x990099 ),
	    9: new THREE.Color( 0xff6600 ),
	    10: new THREE.Color( 0x6666ff )
	};
	
	var geometry = new THREE.Geometry();
	geometry.vertices = vertex;
	var faceIndex = 0;
	for (var faceNum = 0; faceNum < data.face.length; faceNum++)
	{
		for (var i = 0; i < data.face[faceNum].length - 2; i++)
		{
			geometry.faces[faceIndex] = new THREE.Face3( data.face[faceNum][0], data.face[faceNum][i+1], data.face[faceNum][i+2] );
			geometry.faces[faceIndex].color = faceColors[data.face[faceNum].length];
			faceIndex++;
		}
	}
	
	geometry.computeFaceNormals();
	geometry.computeVertexNormals();

	faces = new THREE.Mesh(geometry, faceMaterial);
	polyhedron.add(faces);
	return polyhedron;
}

function cylinderMesh(point1, point2, material)
{
    var direction = new THREE.Vector3().subVectors(point2, point1);
    var arrow = new THREE.ArrowHelper(direction.clone().normalize(), point1);
    var rotation = new THREE.Vector3().setEulerFromQuaternion(arrow.quaternion);
    var edgeGeometry = new THREE.CylinderGeometry( 2, 2, direction.length(), 16, 16 );
    var edge = new THREE.Mesh(edgeGeometry, material); 
    edge.position = new THREE.Vector3().addVectors(point1, direction.multiplyScalar(0.5));
	edge.rotation = rotation;
	return edge;

	// the result should align with:
	//   scene.add( new THREE.ArrowHelper( direction.clone().normalize(), point1, direction.length()) );
}

function animate() 
{
    requestAnimationFrame( animate );
	render();		
	update();
}

function update()
{
	if (camera.position.length() < 150) //console.log(1234);
		camera.position.setLength(150); 
	if (camera.position.length() > 400)
		camera.position.setLength(400);
	
	controls.update();
}

function render() 
{
	renderer.render( scene, camera );
}

</script>

<!-- override dat.gui styles -->
<style>.dg .property-name { width: 95% }</style>

</body>
</html>
